//package com.binance.gateway.filter.limit;
//
//import com.binance.gateway.constant.GwFilterOrders;
//import com.marcosbarbero.cloud.autoconfigure.zuul.ratelimit.config.Rate;
//import com.marcosbarbero.cloud.autoconfigure.zuul.ratelimit.config.RateLimitKeyGenerator;
//import com.marcosbarbero.cloud.autoconfigure.zuul.ratelimit.config.RateLimitUtils;
//import com.marcosbarbero.cloud.autoconfigure.zuul.ratelimit.config.RateLimiter;
//import com.marcosbarbero.cloud.autoconfigure.zuul.ratelimit.config.properties.RateLimitProperties;
//import com.marcosbarbero.cloud.autoconfigure.zuul.ratelimit.support.RateLimitExceededException;
//import com.netflix.zuul.context.RequestContext;
//import lombok.extern.log4j.Log4j2;
//import org.apache.commons.lang3.ArrayUtils;
//import org.springframework.beans.factory.annotation.Value;
//import org.springframework.cloud.netflix.zuul.filters.Route;
//import org.springframework.cloud.netflix.zuul.filters.RouteLocator;
//import org.springframework.http.HttpStatus;
//import org.springframework.stereotype.Component;
//import org.springframework.web.util.UrlPathHelper;
//
//import javax.servlet.http.HttpServletRequest;
//import javax.servlet.http.HttpServletResponse;
//
//import static com.marcosbarbero.cloud.autoconfigure.zuul.ratelimit.support.RateLimitConstants.*;
//import static java.util.concurrent.TimeUnit.MILLISECONDS;
//import static org.springframework.cloud.netflix.zuul.filters.support.FilterConstants.PRE_TYPE;
//
//@Component
//@Log4j2
//public class UrlRateLimitPreFilter extends AbstractRateLimitFilter {
//    @Value("${limit.uri:/exchange-api/v1/private/streamer/order/get-open-orders}")
//    private String[] limitUri;
//    @Value("${limit.count}")
//    private Long limitCount;
//    @Value("${limit.refresh}")
//    private Long limitRefresh;
//    private final RateLimiter rateLimiter;
//
//    public UrlRateLimitPreFilter(RateLimitProperties properties, RouteLocator routeLocator, UrlPathHelper urlPathHelper,
//                                 RateLimiter rateLimiter, RateLimitKeyGenerator rateLimitKeyGenerator, RateLimitUtils rateLimitUtils) {
//        super(properties, routeLocator, urlPathHelper, rateLimitUtils, rateLimitKeyGenerator);
//        this.rateLimiter = rateLimiter;
//    }
//
//    @Override
//    public String filterType() {
//        return PRE_TYPE;
//    }
//
//    @Override
//    public int filterOrder() {
//        return GwFilterOrders.AUTH + 1;
//    }
//
//    @Override
//    public boolean shouldFilter() {
//        HttpServletRequest request = RequestContext.getCurrentContext().getRequest();
//        String uri = request.getRequestURI();
//        return super.shouldFilter() && ArrayUtils.contains(limitUri,uri);
//    }
//
//    @Override
//    public Object run() {
//        final RequestContext ctx = RequestContext.getCurrentContext();
//        final HttpServletResponse response = ctx.getResponse();
//        final HttpServletRequest request = ctx.getRequest();
//        final Route route = route(request);
//        policy(route, request).forEach(policy -> {
//            policy.setLimit(limitCount);
//            policy.setRefreshInterval(limitRefresh);
//            final String key = super.getUserIdUrlKey(request, route, policy);
//            final Rate rate = rateLimiter.consume(policy, key, null);
//            final String httpHeaderKey = key.replaceAll("[^A-Za-z0-9-.]", "_").replaceAll("__", "_");
//
//            final Long remaining = rate.getRemaining();
//            if (limitCount != null) {
//                response.setHeader(HEADER_LIMIT + httpHeaderKey, String.valueOf(limitCount));
//                response.setHeader(HEADER_REMAINING + httpHeaderKey, String.valueOf(Math.max(remaining, 0)));
//            }
//
//            final Long quota = policy.getQuota();
//            final Long remainingQuota = rate.getRemainingQuota();
//            if (quota != null) {
//                request.setAttribute(REQUEST_START_TIME, System.currentTimeMillis());
//                response.setHeader(HEADER_QUOTA + httpHeaderKey, String.valueOf(quota));
//                response.setHeader(HEADER_REMAINING_QUOTA + httpHeaderKey,
//                        String.valueOf(MILLISECONDS.toSeconds(Math.max(remainingQuota, 0))));
//            }
//
//            response.setHeader(HEADER_RESET + httpHeaderKey, String.valueOf(rate.getReset()));
//
//            if (exceedRemaining(limitCount, remaining) || exceedRemainingQuota(quota, remainingQuota)) {
//                ctx.setResponseStatusCode(HttpStatus.TOO_MANY_REQUESTS.value());
//                ctx.put(RATE_LIMIT_EXCEEDED, TRUE);
//                ctx.setSendZuulResponse(false);
//
//                log.warn("Too many request force logout, userId:{}, limitFromSysConfig:{}, limit:{}, remaining:{}, interval:{}, quota:{}, remainingQuota:{}, key:[{}]",
//                        super.getUserId(request), limitCount, limitCount, remaining, policy.getRefreshInterval(), quota, remainingQuota, key);
//
//                // 踢出
//                super.logoutAll();
//
//                throw new RateLimitExceededException();
//            }
//        });
//
//        return null;
//    }
//
//    private boolean exceedRemaining(final Long limit, final Long remaining) {
//        return limit != null && remaining < 0;
//    }
//
//    private boolean exceedRemainingQuota(final Long quota, final Long remainingQuota) {
//        return quota != null && remainingQuota < 0;
//    }
//}
